package com.demo.api.service.user;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.api.interceptor.user.AuthUserInfo;
import com.demo.api.interceptor.user.UserInfo;
import com.demo.client.mapper.user.SysUserMapper;
import com.demo.client.mapper.user.SysUserRoleMapper;
import com.demo.client.model.user.SysDept;
import com.demo.client.model.user.SysUser;
import com.demo.client.model.user.SysUserRole;
import com.demo.api.vo.user.MenuVo;
import com.demo.api.vo.user.UserLogin;
import com.demo.api.vo.user.UserVo;
import com.demo.core.enums.OftenEnum;
import com.demo.core.enums.RedisCacheEnum;
import com.demo.core.redis.RedisCache;
import com.demo.core.redis.RedisTableCache;
import com.demo.core.utils.StringUtils;
import com.demo.core.utils.TokenTools;
import com.demo.core.verification.ValidatorTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Tan-Bowen
 * @version 1.0
 * @description TODO 页面操作（用户操作，角色操作，菜单操作）
 * @date 2021/8/5 10:15
 */
@Slf4j
@Service
public class UserSystemServiceImpl implements IUserSystemService {
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private RedisTableCache redisTableCache;

    @Resource
    private IUserService userService;

    @Resource
    private TokenTools tokenTools;

    @Value("${sys.password}")
    private  String password;

    @Override
    public IPage<UserVo.UserRes> userAll(Page<SysUser> page, UserVo.Select select) {
        LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
        UserInfo user = AuthUserInfo.getUser();
        query.eq(select.getState() != null, SysUser::getState, select.getState());
        query.eq(select.getSex() != null, SysUser::getSex, select.getSex());
        query.eq(select.getDeptId() != null, SysUser::getDeptId, select.getDeptId());
        // 只能读取当前和子级的部门信息
        query.in(!user.getDeptIds().isEmpty(), SysUser::getDeptId, user.getDeptIds());
        query.like(StringUtils.isNotBlank(select.getUserName()), SysUser::getUserName, select.getUserName());
        query.like(StringUtils.isNotBlank(select.getName()), SysUser::getName, select.getName());
        query.like(StringUtils.isNotBlank(select.getTel()), SysUser::getTel, select.getTel());
        IPage<UserVo.UserRes> users = userMapper.selectPage(page, query)
                .convert(sysUser -> BeanUtil.copyProperties(sysUser, UserVo.UserRes.class));
        users.getRecords().forEach(e -> {
            SysDept dept = redisTableCache.get(SysDept.class, e.getDeptId());
            if (dept != null) {
                e.setDeptName(dept.getName());
            }
        });
        return users;
    }

    @Override
    public void create(UserVo.Create request) {
        SysUser user = new SysUser();
        BeanUtils.copyProperties(request, user);
        user.setPassword(ValidatorTools.encryption(password));
        ValidatorTools.checkSqlSuccess(userMapper.insert(user), "添加用户失败");
    }

    @Override
    public void update(UserVo.Update update) {
        SysUser user = new SysUser();
        BeanUtils.copyProperties(update, user);
        ValidatorTools.checkSqlSuccess(userMapper.updateById(user), "编辑用户信息失败");
    }


    @Override
    public SysUser byUserName(String userName) {
        return userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, userName));
    }


    @Override
    @Transactional(rollbackFor = Throwable.class)
    public UserLogin.Response platformLogin(UserLogin.Request login, String ip) {
        SysUser user = this.byUserName(login.getUserName());
        ValidatorTools.commonThrow(user == null, "用户名或密码错误");
        user.setLastLoginIp(ip);
        user.setLastLoginTime(new Date());
        ValidatorTools.commonThrow(OftenEnum.EnableState.DISABLE.eq(user.getState()), "用户未启用");
        ValidatorTools.commonThrow(!ValidatorTools.decrypt(user.getPassword(),login.getPassword()), "用户名或密码错误");
        String token = tokenTools.generateToken(user.getId(), false);
        MenuVo.MenuAndAuth menuAndAuth = userService.getMenuAndAuth(user.getId());
        UserLogin.Response res = BeanUtil.copyProperties(user, UserLogin.Response.class);
        res.setSuperMan(ValidatorTools.isSuper(user.getDeptId()));
        res.setAuth(menuAndAuth.getAuth());
        res.setMenu(menuAndAuth.getMenus());
        res.setToken(token);
        ValidatorTools.checkSqlSuccess(userMapper.updateById(user), "更新用户登录信息失败");
        return res;
    }


    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void deleteUser(Long userId) {
        SysUser user = redisTableCache.get(SysUser.class, userId);
        ValidatorTools.commonThrow(user == null, "用户不存在");
        ValidatorTools.checkSqlSuccess(this.userMapper.deleteById(userId), "删除用户失败！");
        // 删除用户角色
        SysUserRole userRole = redisTableCache.get(SysUserRole.class, userId);
        if (userRole != null) {
            ValidatorTools.checkSqlSuccess(this.userRoleMapper.deleteById(userId), "删除用户失败！");
            redisCache.del(RedisCacheEnum.USER_ROLE.createKey(userId));
        }
        redisTableCache.remove(SysUser.class, userId);
    }

    @Override
    @Transactional
    public void updatePassword(String newPass, String oldPass){
        UserInfo userInfo = AuthUserInfo.getUser();
        SysUser user = redisTableCache.get(SysUser.class,userInfo.getUserId());
        ValidatorTools.isNullThrow(user,"用户不存在");
        String oldPass1 = ValidatorTools.encryption(oldPass);
        ValidatorTools.commonThrow(!ObjectUtils.equals(oldPass1,user.getPassword()),"原密码不正确");
        user.setPassword(ValidatorTools.encryption(newPass));
        ValidatorTools.checkSqlSuccess(userMapper.updateById(user),"修改密码失败");
        redisTableCache.remove(SysUser.class,user.getId());
    }
    @Override
    public List<SysUser> getUsersList(List<Long> userIds){
        return userMapper.selectList(Wrappers.lambdaQuery(SysUser.class).in(SysUser::getId,userIds));
    }

    @Override
    public Map<Long,SysUser> getUsersMap(List<Long> userIds){
        return this.getUsersList(userIds).stream().collect(Collectors.toMap(SysUser::getId, a->a,(b, c)->b));
    }
}
